//
// Created by zhaoyunfei on 20-4-21.
//

#ifndef JFXSSL_SINGLE_TON_HPP
#define JFXSSL_SINGLE_TON_HPP

#include <string>
#include <memory>

template <typename T>
class Singleton {
public:
    template <typename... Args>
    static T* Instance(Args&&... args){
        if(m_pInstance == nullptr){
            m_pInstance.reset(new T(std::forward<Args>(args)...));
        }
        return m_pInstance.get();
    }

    static T* GetInstance(){
        if(m_pInstance == nullptr){
            throw std::logic_error("the instance is not init, please initialize the instance first");
        }
        return m_pInstance.get();
    }

protected:
    Singleton(void)= default;
    Singleton(const Singleton &);
    Singleton &operator = (const Singleton &);

protected:
    static std::unique_ptr<T> m_pInstance;
};

template <class T> std::unique_ptr<T> Singleton<T>::m_pInstance;

/**********************************************************************/

namespace Once {

template <typename T>
class Singleton {
 public:
    template <typename... Args>
    static T *GetInstance(Args &&... args) {
        static std::once_flag sFlag;
        std::call_once(sFlag, [&] { instance_.reset(new T(std::forward<Args>(args)...)); });
        return instance_.get();
    }

 protected:
    Singleton(void) = default;
    Singleton(const Singleton &);
    Singleton &operator=(const Singleton &);

 protected:
    static std::unique_ptr<T> instance_;
};

template <class T>
std::unique_ptr<T> Singleton<T>::instance_;

}

#endif //JFXSSL_SINGLE_TON_HPP
